package diamondServer.clientserver;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Future;

import diamondServer.clientserver.threadpool.PoolManager;
import diamondServer.clientserver.threadpool.ServerTask;



public class Server {

	//	members
	private static Server singleServer = new Server();
	private Selector selector = null;
	private ByteBuffer buffer = ByteBuffer.allocate (1024);
	private PoolManager mgr;
	
	List<Future<String>> result = new ArrayList<Future<String>>();
	OutputStreamWriter log = null; 
	
	//	methods
	private Server() {}
	
	public static Server getInstance() { return singleServer; }
	
	public void init (int port , PoolManager mgr) throws IOException
	{
		this.mgr = mgr;		
		ServerSocketChannel ssc = ServerSocketChannel.open();
		ssc.configureBlocking(false);
		ssc.socket().bind(new InetSocketAddress(port));
		this.selector = Selector.open();
		ssc.register(selector, SelectionKey.OP_ACCEPT);	// registering channel with the selector);
	}
	

	public void go() throws Exception
	{
		while (true)
		{
			int chk = this.selector.select();
			if (chk == 0) continue;	// none of the keys is ready
			else
			{
				Iterator<SelectionKey> it = this.selector.selectedKeys().iterator();
				while (it.hasNext())
				{
					SelectionKey key = it.next();
					
					if (key.isAcceptable())	//	ready to accept
					{
						ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
						SocketChannel sc = ssc.accept();
						sc.configureBlocking(false);
						sc.register(this.selector, SelectionKey.OP_READ);	// registering new channel to read
					}
					if (key.isReadable())	//	ready to read
					{
						this.readData(key);
					}
					
					it.remove();	// done with the key
					
				}
			}
		}
	}

	private void readData(SelectionKey key) throws IOException, InterruptedException
	{
		buffer.clear();
		SocketChannel socketChannel = (SocketChannel) key.channel();	
		
		socketChannel.read (buffer);
		buffer.flip();
		String str = "";
		

		while (buffer.hasRemaining())
			str += ((char) buffer.get());

		socketChannel.close();

		Future<String> fr = mgr.submit(new ServerTask(str));
		this.result.add(fr);
	}
	
}
